#include <sum_btimer.h>
#include <sum_csr.h>
#include <sum_dac.h>
#include <sum_eclic.h>
#include <sum_gpio.h>
#include <sum_rcu.h>
#include <sum_wfi.h>
#include <sys_mem.h>

#define AHB_FREQ_DEFAULT 8000000
#define BTIMER_GAP (AHB_FREQ_DEFAULT >> 12)

// RCU中将GPIOA和DAC上电
static void _enable_gpio_dac(void) {
	rcu_apb1_24_31_s apb1_24_31 = {
		.DAC = 1,
	};
	rcu_apb1_24_31_en_di(apb1_24_31);

	rcu_apb2_0_7_s apb2_0_7 = {
		.GPIOA = 1,
	};
	rcu_apb2_0_7_en_di(apb2_0_7);
}

// 配置GPIO的A4、A5为模拟模式
static void _setup_gpio(void) {
	gpio_ctl_0_7_s gpioa_ctl_0_7 = {
		.pin4_ctl = GPIO_ANALOG,
		.pin5_ctl = GPIO_ANALOG,
	};
	gpio_setup_pin_0_7(GPIOA_Q, gpioa_ctl_0_7);
}

// 定时中断
static void _btimer_irq(void) {
	btimer_refresh(BTIMER_GAP);

	static u16_s count = 0;

	// 获得静态变量count的低12位，存入value。
	struct {
		i16_s count : 12;
	} count_st = {
		.count = count,
	};
	i32_s value = count_st.count;

	// 输出的digital为value绝对值。因此输出值在0到2048之间。
	u32_s sig = value >> 31;
	u32_s digital = (value ^ sig) - sig;
	dac_concurrent_set_12_bit_digital_by_u16(digital, digital);

	// 更新静态变量count，事实上除低12位外高位可以不管。
	count = value + 1;
}

// 中断配置
static void _setup_interrupt(void) {
	// 中断入口地址设为自带的中断入口
	csr_set_default_exti_entry();
	// 中断向量表
	static const __attribute__((aligned(512))) eclic_irqvec_t ivt = {
		.irq_entry_fa[IRQNO_BTIMER] = _btimer_irq,
	};
	eclic_set_ivt_base(&ivt);
	// 设置中断level和priority，其中priority域占据全部bit，无level。
	eclic_set_level_priority_bit_amount(NLBITS_LEVEL_0_PRIORITY_4);
	eclic_clicint_expl_s clicint = {
		.inter_en.value = 1,
		.attr.vector_mode = 0,
		.level_priority = eclic_set_level_priority(
			NLBITS_LEVEL_0_PRIORITY_4, 0, 0),
	};
	eclic_setup_inter_expl(IRQNO_BTIMER, clicint);
	// 打开全局中断
	csr_enable_global_interrupt();
}

// 初始化DAC
static void _init_dac(void) {
	dac_ctl_one_s ctl_one = {
		.dac_en = 1,
		.buf_dis = 0,
		.trig_en = 0,
		.noise_wave_mode = 0,
		.dma_en = 0,
	};
	dac_ctl_expl_s ctl = {
		.dac_ctl_a[0] = ctl_one,
		.dac_ctl_a[1] = ctl_one,
	};
	dac_setup(ctl);
}

__attribute__((noreturn, section(".MAIN"))) void user_main(void) {
	mem_scatter_load();
	_enable_gpio_dac();
	_setup_gpio();
	_init_dac();
	btimer_start(BTIMER_GAP);

	// 异常入口地址直接设为0（理论上该例程中不可能发生异常）。
	csr_enable_eclic_set_entry(0);
	// 中断配置
	_setup_interrupt();

	while (1) {
		wfi();
	}
}
